package core

import (
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"time"
	"zinx_websokect_poker/zinx/ziface"
	"zinx_websokect_poker/zinx_app/poker_game/card"
	"zinx_websokect_poker/zinx_app/poker_game/log"
	"zinx_websokect_poker/zinx_app/poker_game/protocol"
	"zinx_websokect_poker/zinx_app/poker_game/util"
)

//游戏中的玩家类
type Occupant struct {
	*Player
	//ziface.IWSConnection
	room         ziface.IRoom
	cards        card.TCards    //玩家底牌加上公共牌的牌组
	show         *protocol.Show //玩家手里组成的最大的牌型
	Pos          uint8          //玩家座位号，从1开始
	status       int32          // 1为离线状态
	preStatus    int32          // 保存玩家离线前的状态,1为离线状态.
	currentChips []uint32       //每个阶段的下注额
	gameActions  []protocol.UserAction       //每个阶段的下注额
	Bet          uint32         // 当前下注
	actions      chan int32
	actionsResp  chan int32
	waitAction   bool
	chips     	 uint32 // 带入的筹码
	preGameChips uint32 // 游戏初始总记分牌，游戏过程中不会变化
	//HandValue    uint32
	isStandUp    bool  // 玩家是否站起，站起置为true，而不清除玩家数据
}

const (
	Occupant_status_InGame  int32 = 3
	Occupant_status_Offline int32 = 1
	Occupant_status_Observe int32 = 2
	Occupant_status_Sitdown int32 = 0
)

func (o Occupant) IsEmpty() bool {
	return reflect.DeepEqual(o, Occupant{})
}

func (o *Occupant) SetAction(n int32)error {
	if o.waitAction {
		o.actions <- n
		return  nil
	}
	return  errors.New("not your action")
}

func (o *Occupant) SetActionResponse()error {

	o.actionsResp <- 1
	return  nil

	//return  errors.New("not your action")
}

func (o *Occupant) GetAction(timeout time.Duration) int32 {
	//timer := time.NewTimer(timeout)
	timer := util.NewSecondsTimer(timeout)
	//房间保存计时器
	o.room.SetSecondsTimer(timer)

	o.waitAction = true

	select {
	case n := <-o.actions:
		timer.Stop()
		o.waitAction = false
		return n
	//case <-o.room.Closed():
	//	timer.Stop()
	//	o.waitAction = false
	//	return -1
	case <-timer.Timer.C:
		o.waitAction = false
		timer.Stop()
		return 0 // 超时弃牌
	}
}


func (o *Occupant) GetRoom() ziface.IRoom{
	return o.room
}

func (o *Occupant) SetRoom(m ziface.IRoom) {
	o.room = m
}

func (o *Occupant) GetPos() uint8{
	return o.Pos
}

func (o *Occupant) SetPos(p uint8) {
	o.Pos = p
}

func (o *Occupant) GetPlayerid() uint32{
	return o.Pid
}

func (o *Occupant) WriteMsg(msg interface{}) {
	if o.status != Occupant_status_Offline {
		fmt.Println("传输数据给玩家",string(msg.([]byte)))
		log.Info("WriteMsg","用户名：" + o.Nickname + "OutId" + strconv.Itoa(int(o.OutId)) +
			"\n" + string(msg.([]byte)))
		_ = o.Conn.WriteMessage(msg.([]byte))
	}
}

func (o *Occupant) GetActionResponse(msg interface{}){
	t := time.NewTicker(time.Second * 2)
	o.WriteMsg(msg)
	//每两秒循环发送下注信息，直到收到下注响应
	var a = 0
	for {
		if a == 5 {
			break
		}
		select {
		case <-t.C:
			o.WriteMsg(msg)
		case <-o.actionsResp:
			goto End
		}
		a ++
	}
	End :
}

func (o *Occupant) SetData(d interface{}){
	o.Player = d.(*Player)
}

func (o *Occupant) SetObserve() {
	o.status = Occupant_status_Observe
}

func (o *Occupant) IsObserve() bool {
	return o.status == Occupant_status_Observe
}

func (o *Occupant) SetOffline() {
	if o != nil {
		log.Info("DoConnectionLost","【连接中断】用户名：" + o.Nickname + "OutId" + strconv.Itoa(int(o.OutId)))
		//连接中断前，将当前状态保存起来.
		o.preStatus = o.status
		o.status = Occupant_status_Offline
	}
}

func (o *Occupant) IsOffline() bool {
	return o.status == Occupant_status_Offline
}

func (o *Occupant) SetSitdown() {
	o.preStatus = Occupant_status_Sitdown
	o.status = Occupant_status_Sitdown
}

func (o *Occupant) IsSitdown() bool {
	return o.status == Occupant_status_Sitdown
}

func (o *Occupant) SetGameing() {
	fmt.Println("设置玩家为游戏状态",o.Nickname)
	if o.status != Occupant_status_Offline  {
		o.status = Occupant_status_InGame
	}
}

func (o *Occupant) IsGameing() bool {
	if o == nil {
		return false
	}
	return o.status == Occupant_status_InGame
}

//掉线重连时替换数据
func (o *Occupant) Replace(value *Occupant) {
	o.Pos   = value.Pos
	o.Bet   = value.Bet
	o.cards = value.cards
	o.room  = value.room
	o.RoomID  = value.RoomID
	o.chips = value.chips
	o.status = value.preStatus
	o.currentChips = value.currentChips
}

func NewOccupant(data *Player, conn ziface.IWSConnection) *Occupant {
	o := &Occupant{
		Player:    data,
		actions: make(chan int32),
		//actionsResp: make(chan int32),
		show: &protocol.Show{},
	}
	OccupantMgrObj.Add(o)
	return o
}